iT邦幫忙

2022 iThome 鐵人賽

DAY 30
2
Modern Web

Nuxt 3 學習筆記系列 第 30

[Day 30] Nuxt 3 就剩最後一步了 - 部署 (Deployment)

  • 分享至 

  • xImage
  •  

前言

我們完成網站的開發與建構後,將會將網站部署至正式環境,前一篇我們介紹了建構與打包的相關指令與參數配置,這篇文章將舉幾個例子來實際部署我們的專案。

Nuxt 3 的部署方式

Nuxt 3 的專案應用程式,可以部署在 Node.js 的伺服器上面,也可以將預渲染的靜態網站由靜態託管平台來服務,或這部署至無伺服器 (serverless) 或 CDN 環境上。

使用 Node.js 伺服器

Nuxt 3 的專案預設使用 Nitro 來作為服務引擎,所以我們在任何 Node.js 伺服器環境之下,基本上都可以啟動 Nuxt 的建置出來的 Nitro Server。

當我們使用 npm run build 建構專案後,輸出的 .output/server/index.mjs 檔案,即是一個準備啟動 Node 伺服器的入口點。

我們可以透過下列指令來啟動我們建構好的專案。

node .output/server/index.mjs

執行後如下面圖示顯示,網站將於 Prot: 3000 進行服務監聽。
https://ithelp.ithome.com.tw/upload/images/20221015/20152617KBXtweHeCR.png

你可以設定下列環境變數來調整預設監聽的 PortHost

  • NITRO_PORTPORT: 監聽的 Port (預設為 3000)
  • NITRO_HOSTHOST: 服務的 Host (沒有預設值,但預設監聽所有的網路介面包含 IPv4 與 IPv6 的位址 )
  • NITRO_SSL_CERTNITRO_SSL_KEY: 如果兩者皆設定,將以 HTTPS 模式下啟動伺服器,通常僅作為測試用途,因為建議將 SSL 憑證等設定於提供反向代理的服務,例如 NGINX 或 CloudFlare,Nitro 伺服器則執行在反向代理後面。

部署時,你可以將整個 .output 上傳至正式環境的機器上,並使用 Node.js 做執行,但為了防止我們的服務因為異常,導致 Node.js 服務意外崩潰,我們需要一個 ProcessDaemon,來將服務常駐,意外崩潰時能自動重啟,來維持整個網站的正常服務。

通常我們會在正式環境使用 PM2 來管理 Node.js 的服務,PM2 是維持一個 Process 執行的管理器,我們可以藉由 PM2 來啟動我們的 Nitro Server,當服務崩潰時能自動的重新啟動,以維持服務的正常運作,除此之外 PM2 可以啟用叢集 (Cluster) 的功能結合請求的附載平衡,來讓多核心的機器提升資源的利用率與效能,更還有監測多項數據等功能可供正式環境做使用。

使用的方式也很簡單,首先使用 NPM 安裝 PM2,可以執行下列指令:

npm install -g pm2

在 Nuxt 專案目錄下建立 ecosystem.config.js 檔案,內容如下:

module.exports = {
  apps: [
    {
      name: 'NuxtAppName',
      exec_mode: 'cluster',
      instances: 'max',
      script: './.output/server/index.mjs'
    }
  ]
}

接著我們就能使用 PM2 來執行我們的服務:

pm2 start ecosystem.config.js

https://i.imgur.com/G7sujsl.gif

你也可以在ecosystem.config.js 中添加環境變數。

module.exports = {
  apps: [
    {
      name: 'NuxtAppName',
      exec_mode: 'cluster',
      instances: 'max',
      script: './.output/server/index.mjs',
      env: {
        NITRO_PORT: 3001,
        NITRO_HOST: '127.0.0.1'
      }
    }
  ]
}

製作 Docker Image

目前使用 Docker 來部署服務的也不在少數,個人也是採用容器化來啟動網站服務並整合 CI/CD 自動化的流程來建構與部署 Nuxt 3 專案,以下將列出自己使用的 Dockerfile,有興趣的可以再參考看看。

專案目錄下建立 Dockerfile 檔案,內容如下:

FROM node:16-alpine AS builder

RUN mkdir -p /nuxt-app
WORKDIR /nuxt-app
COPY . .

RUN npm ci && npm cache clean --force
RUN npm run build


FROM keymetrics/pm2:16-alpine

RUN mkdir -p /nuxt-app/.output
WORKDIR /nuxt-app/.output

COPY --from=builder /nuxt-app/.output .
COPY ./ecosystem.config.js /nuxt-app

ENV NUXT_HOST=0.0.0.0
ENV NUXT_PORT=3000

EXPOSE 3000 

ENTRYPOINT ["pm2-runtime", "start", "/nuxt-app/ecosystem.config.js"]

打開終端機 (Terminal),並於專案目錄下執行下列指令:

docker build -t nuxt-app .

當開始製作 Docker Image 時,會依照Dockerfile 來建置,主要分成兩個部分,首先我會先在 node:16-alpine 容器環境中執行建構 (build) 的指令,並將需要部署的目錄 .output 複製至 keymetrics/pm2:16-alpine 容器環境中,這樣最終使用 PM2 執行服務的 Image 大小就會稍微小一些。

當 Docker Image 製作完畢後,可以再藉由 docker run 或 docker compose 甚至 k8s 來啟動服務後,再由如 NGINX 提供反向代理服務連接到內部的 Nitro Server。

部署至 CloudFlare Workers

我們也可以將 Nuxt 部署到無伺服器 (Serverless) 的環境,官方提供了多種的預設部署可以做使用,我們就簡單以一個乾淨的 Nuxt 3 專案來做範例,嘗試部署到 CloudFlare Workers

首先,我們先準備一個 Nuxt 3 專案,在此我使用下列指令建立一個乾淨的 Nuxt 3 專案,並進入專案目錄安裝套件:

npx nuxi init nuxt-app
cd nuxt-app
npm install

使用 NPM 安裝 wrangler,它是用於建構 Cloudflare Workers 的命令列工具 (command line tool)。

npm install -g wrangler

你可能需要註冊一個 CloudFlare 的帳號,並使用下列指令來登入 CloudFlare 帳號並授權 Wrangler 來建立 CloudFlare Workers,我們選擇允許 (Allow) 即可。

wrangler login

於專案目錄下建立 wrangler.toml 內容如下:

name = "nuxt-app-hello"
main = "./.output/server/index.mjs"
workers_dev = true
compatibility_date = "2022-10-15"

[site]
bucket = ".output/public"

我們將 NITRO_PRESET 環境變數,設置為 cloudflare 並開始建構我們的專案。

NITRO_PRESET=cloudflare npm run build

https://ithelp.ithome.com.tw/upload/images/20221015/201526172BmCfsiOlD.png

接下來,可以選擇執行終端機提示的指令來啟動伺服器進行相關測試。

npx wrangler dev .output/server/index.mjs --site .output/public --local

https://ithelp.ithome.com.tw/upload/images/20221015/20152617DW11WZgcdK.png

當確認專案服務運作上沒問題後,可以執行下列指令進行發布。

npx wrangler publish

完成發布後,就會提示我們發布完成及服務的網址,例如 https://nuxt-app-hello.ryanchien8125.workers.dev,我們就可以瀏覽我們部署好的網站囉。
https://ithelp.ithome.com.tw/upload/images/20221015/201526172DbBFoaoXn.png

靜態的網站部署至 CloudFlare Pages

我們使用 Nuxt 3 可以預渲染全靜態的網站,因此也可以將專案部署至靜態託管平台,以 CloudFlare Pages 為例,部署的步驟如下:

首先,先執行下列指令進行全站的預渲染:

npm run generate

使用 NPM 安裝 wrangler

npm install -g wrangler

你可能需要註冊一個 CloudFlare 的帳號,並使用下列指令來登入 CloudFlare 帳號並授權 Wrangler,我們選擇允許 (Allow) 即可。

wrangler login

建立一個 CloudFlare Pages 名為 nuxt-app-blog

wrangler pages project create nuxt-app-blog

https://ithelp.ithome.com.tw/upload/images/20221015/20152617z7bL43bE94.png

使用下列指令,將預渲染的網站目錄進行部署,並指定專案名稱為 nuxt-app-blog

wrangler pages publish ./.output/public --project-name nuxt-app-blog

當部署完成後,就會得到一個連結來查看部署的靜態網頁,你也可以從 CloudFlare Pages 後台,看見網站網址的別名 Aliases 來使用自訂的網址。
https://ithelp.ithome.com.tw/upload/images/20221015/20152617bjIpuYkIxF.png

以上是介紹 Nuxt 3 的幾個部署方式的例子,更多雲端平台上面的部署,也可以參考 Nuxt 與 Nitro 官方文件。


上線前的測試項目

最後與大家分享一下網站專案上線前的幾個我會特別注意的幾個小細節,也歡迎大家一起來交流。

前端細節

  • 網頁的標題 (Title)
  • 使用之資源授權 (使用權、智財權)
  • 圖片替代文字
  • Favicon
  • HTML Meta data
  • Google Analytics

瀏覽器相容性測試

  • RWD
  • 跨瀏覽器
    • BrowserStack
    • Comparium
    • TestingBot

API 測試

  • 單元測試
  • 不同場景測試 (測試環境、正式環境)
  • 效能測試
    • JMeter
    • k6
  • 安全性測試

壓力測試

  • 模擬使用者或連線數
  • 觀察機器資源使用量
  • 資料庫連線數觀察
  • 持續提高模擬數量觀察分析
  • 分析每個請求於併發的平均響應時間
  • 是否請求中夾雜非預期之狀態碼 (HTTP Status Code)

API 或網站安全性

  • 參考 OWASP Top 10
  • SQL 參數化查詢
  • 資安公司滲透測試、紅隊演練

開發或除錯用的訊息

  • 警告訊息或異常訊息移除(console.log 或警告訊息等)
  • JavaScript Source Maps 記得移除
  • 敏感資訊記得移除 (開發用 Key、帳號密碼等)

網站相依性檢查

  • 使用到第三方網站資源及穩定性
  • 檢查所有網址皆能正常運作
  • 當第三方網站異常時應對措施

部署相關

  • 是否有高可用性 (HA)
  • Docker 或 Kubernetes 整合
  • 網域時效
  • SSL 證書日期
  • 防火牆或 WAF 設定
  • 內網或外網區隔

備份機制

  • 靜態有狀態資料 (使用者上傳的)
  • 資料庫資料

小結

這邊主要與大家分享幾種 Nuxt 的部署方式,不管是部署在自己的機房主機或雲端,大家可以在挑選合適的解決方案,Nitro 也支援無伺服器 (Serverless) 等部署方式非常的方便,只是要特別注意到 Serverless 執行一些 binary 的問題,再挑選自己適合的部署與服務方式。

今年的鐵人賽終於告一段落了,恭喜自己能完成這次的挑戰,也感謝另一半與毛小孩給予能量鼓勵,祝大家學習 Nuxt 與網站開發能一切順利。


感謝大家的閱讀,這是我第一次參加 iThome 鐵人賽,請鞭小力一些,也歡迎大家給予建議 :)
如果對這個 Nuxt 3 系列感興趣,可以訂閱接收通知,也歡迎分享給喜歡或正在學習 Nuxt 3 的夥伴。

參考資料


上一篇
[Day 29] Nuxt 3 發布網站前的建構打包 (Build) 與靜態網站生成 (Static Site Generation)
系列文
Nuxt 3 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
Global Rachel
iT邦新手 3 級 ‧ 2022-10-18 16:59:53

恭喜完賽!每一篇都是乾貨滿滿~

Ryan iT邦新手 1 級 ‧ 2022-10-19 00:00:26 檢舉

謝謝 :)

0

謝謝,覺得 Nuxt3 快要推出了,正在找學習資源,每一篇都很扎實,謝謝您!

Ryan iT邦新手 1 級 ‧ 2022-11-04 02:02:49 檢舉

非常感謝您的閱讀,希望這個系列有幫助到您 :)

0
fgfg98231
iT邦新手 5 級 ‧ 2022-12-22 15:02:22

看下來3好像是大升級
Nuxt2年初才剛學習,不知道能不能無痛使用3/images/emoticon/emoticon02.gif

Ryan iT邦新手 1 級 ‧ 2022-12-22 23:58:42 檢舉

是需要時間來熟一下,不過 Nuxt 3 是真的更好用

1
Johnson
iT邦新手 5 級 ‧ 2023-02-08 21:05:50

謝謝大大分享,每篇都好厲害!

Ryan iT邦新手 1 級 ‧ 2023-02-09 13:23:45 檢舉

希望有幫助到您:)

1
Wayne
iT邦新手 4 級 ‧ 2023-02-09 09:04:05

先收藏一波了!感謝Ryan大大的乾貨!

Ryan iT邦新手 1 級 ‧ 2023-02-09 13:23:46 檢舉

謝謝您不嫌棄:)

0
Robby
iT邦新手 5 級 ‧ 2023-07-08 21:56:06

感謝分享,2023 年中了,Nuxt3 也漸漸成熟,最近開始著手學習,受益良多!!!

Ryan iT邦新手 1 級 ‧ 2024-01-02 15:16:00 檢舉

謝謝您

/images/emoticon/emoticon12.gif

0
blueberry633
iT邦新手 3 級 ‧ 2023-12-31 16:58:33

感謝教學分享~

Ryan iT邦新手 1 級 ‧ 2024-01-02 15:16:00 檢舉

謝謝您

/images/emoticon/emoticon12.gif

我要留言

立即登入留言